﻿/*
	Copyright 2009 Jason Nottingham

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.


    How to submit a patch:
    1. create or modify a test case (under 'tests') so that it fails to compile/link/run without 
       your change
    2. verify you have the latest sources (resync/merge)
    3. fix or add the missing functionality
    4. verify that your changes fixes the newly broken test case in #1 - it now builds and runs 
       C++ the same as the original C#
    5. create a Subversion-friendly diff or patch file of your changes (including the test cases)
    6. submit your patch at http://gonative.codeplex.com


*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace GoNative
{

    /// <summary>
    /// 
    /// </summary>
    class ProjectFile
    {
        private readonly string name;
        private readonly bool windowsApp;
        private readonly SourceFile[] sourceFiles;

        public string Name
        {
            get { return name; }
        }

        public SourceFile[] SourceFiles
        {
            get { return sourceFiles; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileName"></param>
        public ProjectFile(string fileName)
        {
            name = fileName;
            windowsApp = true;
            FileInfo fi = new FileInfo(name);
            string[] lines = File.ReadAllLines(name);
            List<SourceFile> sources = new List<SourceFile>();
            foreach (string line in lines)
            {
                if (line.Contains("<Compile Include="))
                {
                    string[] fields = line.Split('"');
                    if (fields.Length > 1)
                    {
                        string sourceFile = fields[1].ToUpperInvariant();
                        if (!sourceFile.Contains(".DESIGNER.CS") && !sourceFile.Contains("ASSEMBLYINFO.CS"))
                        {
                            // .designer.cs files are already processed when the main class file is processed
                            string directoryName = fi.DirectoryName;
                            if (string.IsNullOrEmpty(directoryName))
                                directoryName = ".";
                            sourceFile = Path.Combine(directoryName, fields[1]);
                            if (File.Exists(sourceFile))
                                sources.Add(new SourceFile(sourceFile));
                        }
                    }
                }
                if ( line.Contains("<OutputType>Exe</OutputType>") )
                    windowsApp = false;
            }

            sourceFiles = sources.ToArray();
        }

        /// <summary>
        /// 
        /// </summary>
        internal void Process()
        {
            Console.WriteLine("  Processing project file {0}", name);
            string commonHeaders = DetermineCommonHeaders(sourceFiles);
            foreach (SourceFile source in sourceFiles)
                source.Process(windowsApp,commonHeaders);
        }

        private static string DetermineCommonHeaders(IEnumerable<SourceFile> files)
        {
            StringBuilder sb = new StringBuilder("#include \"commctrl.h\"\n");
            foreach (SourceFile source in files)
                sb.AppendFormat("#include \"{0}\"\n", 
                    Path.GetFileName(source.HeaderFileName));
            return sb.ToString();
        }
    }
}
